import numpy as np
import geatpy as ea


class MyProblem(ea.Problem):  # 继承Problem父类

    def __init__(self):
        name = 'MyProblem'  # 初始化name（函数名称，可以随意设置）
        M = 2             # 初始化M（目标维数）
        maxormins = [1, 1]  # 初始化maxormins（目标最小最大化标记列表，1：最小化该目标；-1：最大化该目标）
        Dim = 2           # 初始化Dim（决策变量维数x1,x2,x3）
        varTypes = [1] * Dim  # 初始化varTypes（决策变量的类型，元素为0表示对应的变量是连续的；1表示是离散的）
        lb = [0, 0]  # 决策变量下界
        ub = [5, 3]  # 决策变量上界
        lbin = [1, 1]  # 决策变量下边界（0表示不包含该变量的下边界，1表示包含）
        ubin = [1, 1]  # 决策变量上边界（0表示不包含该变量的上边界，1表示包含）
        # 调用父类构造方法完成实例化
        ea.Problem.__init__(self, name, M, maxormins, Dim, varTypes, lb, ub, lbin, ubin)

    def evalVars(self, Vars):  # 目标函数
        x1 = Vars[:, [0]]
        x2 = Vars[:, [1]]
        f1 = 4*x1**2 + 4*x2**2 # 目标函数的值
        f2 = 4*(x1-5)**2 + 4*(x2-5)**2
        f = np.hstack([f1, f2])
        # 采用可行性法则处理约束
        CV = np.hstack(  # hstack是水平顺序堆叠数组（按列）。
            [(x1-5)**2 + x2**2 - 25, 7.7 - (x1-8)**2 - (x2-3)**2])
        return f, CV


if __name__ == '__main__':
    # 实例化问题对象
    problemx = MyProblem()
    # 构建算法
    algorithmx = ea.moea_NSGA2_templet(
        problemx,
        ea.Population(Encoding='RI', NIND=100),
        MAXGEN=200,  # 最大进化代数。
        logTras=1)  # 表示每隔多少代记录一次日志信息，0表示不记录。
    algorithmx.mutOper.F = 0.2  # 差分进化中的参数F
    algorithmx.recOper.XOVR = 0.9  # 重组概率
    # 求解
    resx = ea.optimize(algorithmx,verbose=True, drawing=1, outputMsg=True, drawLog=True, saveFlag=True)
    print(resx)
